home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / lisp / elk-2_0.lha / elk-2.0 / src / env.c < prev    next >
C/C++ Source or Header  |  1992-10-05  |  5KB  |  216 lines

  1. /* Environments, define, set!, etc.
  2.  */
  3.  
  4. #include "scheme.h"
  5.  
  6. Object The_Environment, Global_Environment;
  7.  
  8. Object List_To_Env(), General_Define();
  9.  
  10. Init_Env () {
  11.     Global_Environment = The_Environment = List_To_Env (Cons (Null, Null));
  12.     Global_GC_Link (Global_Environment);
  13.     Global_GC_Link (The_Environment);
  14. }
  15.  
  16. Object Env_To_List (env) Object env; {
  17.     Object p;
  18.  
  19.     p = env;
  20.     SETTYPE(p, T_Pair);
  21.     return p;
  22. }
  23.  
  24. Object List_To_Env (list) Object list; {
  25.     Object e;
  26.  
  27.     e = list;
  28.     SETTYPE(e, T_Environment);
  29.     return e;
  30. }
  31.  
  32. Object P_Env_List (env) Object env; {
  33.     Check_Type (env, T_Environment);
  34.     return Copy_List (Env_To_List (env));
  35. }
  36.  
  37. Object P_Environmentp (x) Object x; {
  38.     return TYPE(x) == T_Environment ? True : False;
  39. }
  40.  
  41. Push_Frame (frame) Object frame; {
  42.     Object e;
  43.  
  44.     Memoize_Frame (frame);
  45.     e = Env_To_List (The_Environment);
  46.     The_Environment = List_To_Env (Cons (frame, e));
  47. }
  48.  
  49. Pop_Frame () {
  50.     Object e;
  51.     
  52.     e = Env_To_List (The_Environment);
  53.     The_Environment = List_To_Env (Cdr (e));
  54.     Forget_Frame (Car (e));
  55. }
  56.  
  57. Switch_Environment (to) Object to; {
  58.     Object old, new;
  59.  
  60.     if (EQ(The_Environment,to))
  61.     return;
  62.     old = Env_To_List (The_Environment);
  63.     new = Env_To_List (to);
  64.     for ( ; !Nullp (old); old = Cdr (old)) {
  65.     for (new = Env_To_List (to); !Nullp (new) && !EQ(new,old);
  66.         new = Cdr (new))
  67.         ;
  68.     if (EQ(new,old))
  69.         break;
  70.     Forget_Frame (Car (old));
  71.     }
  72.     Memoize_Frames (Env_To_List (to), new);
  73.     The_Environment = to;
  74. }
  75.  
  76. Memoize_Frames (this, last) Object this, last; {
  77.     if (Nullp (this) || EQ(this,last))
  78.     return;
  79.     Memoize_Frames (Cdr (this), last);
  80.     Memoize_Frame (Car (this));
  81. }
  82.  
  83. Memoize_Frame (frame) Object frame; {
  84.     Object tail, binding;
  85.  
  86.     for (tail = frame; !Nullp (tail); tail = Cdr (tail)) {
  87.     binding = Car (tail);
  88.     SYMBOL(Car (binding))->value = Cdr (binding);
  89.     }
  90. }
  91.  
  92. Forget_Frame (frame) Object frame; {
  93.     Object tail;
  94.  
  95.     for (tail = frame; !Nullp (tail); tail = Cdr (tail))
  96.     SYMBOL(Car (Car (tail)))->value = Unbound;
  97. }
  98.  
  99. Object Add_Binding (frame, sym, val) Object frame, sym, val; {
  100.     Object b;
  101.     GC_Node;
  102.  
  103.     GC_Link (frame);
  104.     b = Cons (sym, val);
  105.     frame = Cons (b, frame);
  106.     GC_Unlink;
  107.     return frame;
  108. }
  109.  
  110. Object Lookup_Symbol (sym, err) Object sym; {
  111.     Object p, b;
  112.  
  113.     for (p = Env_To_List (The_Environment); !Nullp (p); p = Cdr (p)) {
  114.     b = Assq (sym, Car (p));
  115.     if (!EQ(b, False))
  116.         return b;
  117.     }
  118.     if (err)
  119.     Primitive_Error ("unbound variable: ~s", sym);
  120.     return Null;
  121. }
  122.  
  123. Object P_The_Environment () { return The_Environment; }
  124.  
  125. Object P_Global_Environment () { return Global_Environment; }
  126.  
  127. Object Define_Procedure (form, body, sym) Object form, body, sym; {
  128.     Object ret;
  129.     GC_Node3;
  130.  
  131.     GC_Link3 (form, body, sym);
  132.     body = Cons (Cdr (form), body);
  133.     body = Cons (sym, body);
  134.     body = Cons (body, Null);
  135.     body = Cons (Car (form), body);
  136.     ret = General_Define (body, sym);
  137.     GC_Unlink;
  138.     return ret;
  139. }
  140.  
  141. Object General_Define (argl, sym) Object argl, sym; {
  142.     Object val, var, frame, binding;
  143.     GC_Node3;
  144.  
  145.     var = Car (argl);
  146.     val = Cdr (argl);
  147.     if (TYPE(var) == T_Symbol) {
  148.     frame = Null;
  149.     GC_Link3 (var, val, frame);
  150.     if (Nullp (val))
  151.         val = Void;
  152.     else
  153.         val = Eval (Car (val));
  154.     Set_Name (var, val);
  155.     frame = Car (The_Environment);
  156.     binding = Assq (var, frame);
  157.     if (EQ(binding, False)) {
  158.         frame = Add_Binding (frame, var, val);
  159.         Car (The_Environment) = frame;
  160.     } else
  161.         Cdr (binding) = val;
  162.     SYMBOL(var)->value = val;
  163.     GC_Unlink;
  164.     return var;
  165.     } else if (TYPE(var) == T_Pair) {
  166.     if (Nullp (val))
  167.         Primitive_Error ("no sub-forms in compound: ~s", var);
  168.     return Define_Procedure (var, val, sym);
  169.     } else Wrong_Type_Combination (var, "symbol or pair");
  170.     /*NOTREACHED*/
  171. }
  172.  
  173. Object P_Define (argl) Object argl; {
  174.     return General_Define (argl, Sym_Lambda);
  175. }
  176.  
  177. Object P_Define_Macro (argl) Object argl; {
  178.     return General_Define (argl, Sym_Macro);
  179. }
  180.  
  181. Object P_Set (argl) Object argl; {
  182.     Object val, var, binding, old;
  183.     GC_Node3;
  184.  
  185.     var = Car (argl);
  186.     val = Car (Cdr (argl));
  187.     Check_Type (var, T_Symbol);
  188.     binding = Lookup_Symbol (var, 1);
  189.     old = Cdr (binding);
  190.     GC_Link3 (var, binding, old);
  191.     val = Eval (val);
  192.     Set_Name (var, val);
  193.     Cdr (binding) = val;
  194.     SYMBOL(var)->value = val;
  195.     GC_Unlink;
  196.     return old;
  197. }
  198.  
  199. Set_Name (var, val) Object var, val; {
  200.     register t;
  201.  
  202.     t = TYPE(val);
  203.     if (t == T_Compound) {
  204.     if (Nullp (COMPOUND(val)->name))
  205.         COMPOUND(val)->name = var;
  206.     } else if (t == T_Macro) {
  207.     if (Nullp (MACRO(val)->name))
  208.         MACRO(val)->name = var;
  209.     }
  210. }
  211.  
  212. Object P_Boundp (x) Object x; {
  213.     Check_Type (x, T_Symbol);
  214.     return Nullp (Lookup_Symbol (x, 0)) ? False : True;
  215. }
  216.